package org.bigjava.novelplatform.common.exception.controllerAdivce;

import lombok.extern.slf4j.Slf4j;
import org.bigjava.novelplatform.common.exception.OrderException;
import org.bigjava.novelplatform.common.exception.UserActionException;
import org.bigjava.novelplatform.common.utils.R;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.method.HandlerMethod;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.*;

import static org.bigjava.novelplatform.common.exception.ExceptionCodeMessage.FIELD_ERROR;
import static org.bigjava.novelplatform.common.exception.ExceptionCodeMessage.UNKNOWN_ABNORMAL;

/**
 * 全局异常处理器
 * @author ykh
 * @create 2022-03-20 18:19
 */
@Slf4j
@RestControllerAdvice(basePackages = "org.bigjava.novelplatform.controller")
public class ExceptionControllerAdvice {

    /**
     * bean字段绑定异常
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R fieldException(WebRequest w, HandlerMethod m, MethodArgumentNotValidException e){
        log.warn("请求处理程序{}，方法{}，请求参数{}",m.getShortLogMessage(),m.getMethod(),m.getMethodParameters(),e);
        BindingResult bindingResult = e.getBindingResult();
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        HashMap<String, String> errMap = new HashMap<>();
        fieldErrors.forEach((error)->{
            errMap.put(error.getField(),error.getDefaultMessage());
        });
        return R.error(FIELD_ERROR).setData(errMap);
    }




    /**
     * controller参数校验异常
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public R fieldException(ConstraintViolationException e){
        log.warn(e.getMessage());
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        Iterator<ConstraintViolation<?>> iterator = constraintViolations.iterator();
        List<String> msgList = new ArrayList<>();
        while (iterator.hasNext()) {
            ConstraintViolation<?> cvl = iterator.next();
            msgList.add(cvl.getMessageTemplate());
        }
        return R.error(FIELD_ERROR).setData(msgList);
    }

    /**
     * 购买异常
     * @param e
     * @return
     */
    @ExceptionHandler(OrderException.class)
    public R UserActionException(OrderException e){
        log.error(e.getCodeMessage().getMessage());
        if (e.getData() != null) {
            return R.error(e.getCodeMessage()).setData(e.getData());
        }
        return R.error(e.getCodeMessage());
    }



    /**
     * 用户操作异常
     * @param e
     * @return
     */
    @ExceptionHandler(UserActionException.class)
    public R UserActionException(UserActionException e){
        log.warn(e.getCodeMessage().getMessage());
        return R.error(e.getCodeMessage());
    }

    /**
     * 其他异常
     * @param e
     * @return
     */
    @ExceptionHandler(Throwable.class)
    public R otherException(Exception e){
        log.error(e.getMessage());
        e.printStackTrace();
        return R.error(UNKNOWN_ABNORMAL);
    }
}
